/**
 * 责任链模式：
 *     类似多米诺骨牌，通过请求一个条件，会持续执行后续条件，直到返回结果为止。
 */

/**
 * 场景：
 *    某电商针对已经付过定金的用户具有优惠政策。
 *    在正式购买后，1、已经支付500元定金的用户会受到100元优惠卷
 *                 2、已经支付200元定金的用户会受到50元优惠卷
 *                 3、没有支付定金的用户，只能正常购买。
 */

/**
 * 
 * @param {*} orderType: 訂單類型 ： 1： 500元定金
 *                                  2： 200元定金 
 *                                  3： 没有定金 
 * @param {*} pay 
 * @param {*} stock 
 */
const order500 = function(orderType, pay, stock) {
    if(orderType === 1 && pay === true) { 
      console.log("500元定金预定，得到100元优惠券。")
    } else {
        order200(orderType,pay, stock)
    }
}

const order200 = function(orderType, pay, stock) {
    if(orderType === 2 && pay === true) { 
      console.log("200元定金预定，得到50元优惠券。")
    } else {
        orderCommon(orderType, pay, stock)
    }
}

const orderCommon = function(orderType, pay, stock) {
    if (orderType === 3 && pay === true) {
        console.log("普通购买，无优惠券。")
    } else {
        console.log("库存不够，无法购买。")
    }
}

// order500(3, true, 500) // 普通购买，无优惠券。

/**
 * 改造一下
 *    重构后，链路代码 和 业务代码 彻底的分离。 
 *    假如未来还需要增加order300那只需要新增与其相关的函数，而不必改原有的业务代码。
 */
const orderFiveHundred = function(orderType, pay, stock) {
    if (orderType === 1 && pay === true) {
        console.log("500元定金预定，得到100元优惠券。")
    } else {
        return "nextSuccess"
    }
} 
const orderTwoHundred = function(orderType, pay, stock) {
    if(orderType === 2 && pay === true) { 
      console.log("200元定金预定，得到50元优惠券。")
    } else {
        return "nextSuccess"
    }
} 
const orderPrimary = function (orderType, pay, stock) {
    console.log(orderType, pay, stock)
    if (orderType === 3 && stock > 0) {
        console.log("普通购买，无优惠券。")
    } else {
        console.log("库存不够，无法购买。")
    }
} 

const chain = function (fn) { 
    this.fn = fn
    this.successor = null
}

chain.prototype.setNext = function (successor) {
    this.successor = successor
}

chain.prototype.init = function() {
    const result = this.fn.apply(this, arguments)
    if (result === "nextSuccess") { 
        this.successor.init.apply(this.successor,arguments)
    }
}

const o500New = new chain(orderFiveHundred) 
const o200New = new chain(orderTwoHundred)
const oPrimary = new chain(orderPrimary)

o500New.setNext(o200New)
o200New.setNext(oPrimary)

// o500New.init(3, true, 500) // 普通购买，无优惠券。

/**
 * 结合AOP还能简化上述链路代码
 */
Function.prototype.after = function(fn) {
    const self = this
    return function() {
        const result = self.apply(self, arguments)
        if (result === "nextSuccess") { 
            return fn.apply(self,arguments)
        }
    }
}

const order = orderFiveHundred.after(orderTwoHundred).after(orderPrimary)

order(3, true, 500) // 普通购买，无优惠券。